package com.moneywelcome.orderassembly.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.moneywelcome.exceptions.MwcArgsException;
import com.moneywelcome.orderassembly.model.FinancialShares;
import com.moneywelcome.orderassembly.model.RedeemRecord;
import com.moneywelcome.orderassembly.mapper.RedeemRecordMapper;
import com.moneywelcome.orderassembly.model.UserFinancial;
import com.moneywelcome.orderassembly.service.FinancialSharesService;
import com.moneywelcome.orderassembly.service.RedeemRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moneywelcome.orderassembly.service.UserFinancialService;
import com.moneywelcome.orderassembly.util.GoldUtil;
import com.moneywelcome.orderfacade.dto.RedeemOrderDto;
import com.moneywelcome.orderfacade.vo.OrderPageVo;
import com.moneywelcome.orderfacade.vo.RedeemRecordVo;
import com.moneywelcome.results.PageResult;
import com.moneywelcome.results.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 赎回记录表 服务实现类
 * </p>
 *
 * @author alice
 * @since 2022-01-06
 */
@Service
public class RedeemRecordServiceImpl extends ServiceImpl<RedeemRecordMapper, RedeemRecord> implements RedeemRecordService {
    @Autowired
private UserFinancialService ufs;
    @Autowired
    private FinancialSharesService fss;
    @Override
    public RedeemOrderDto create(RedeemRecordVo redeemRecordVo) {
        UserFinancial financial = ufs.getById(redeemRecordVo.getFinancialId());
        if(null==financial) throw new MwcArgsException( "持仓不存在",StatusCode.Error);
        if((financial.getFinancialShares()-redeemRecordVo.getRedeemShares())<0) throw new MwcArgsException( "赎回份额不足",StatusCode.Error);
        RedeemRecord redeem = BeanUtil.copyProperties(redeemRecordVo, RedeemRecord.class);
        redeem.setGoldId(financial.getGoldId());
        redeem.setVariety(financial.getVariety());
        redeem.setRedeemRecordStatus(0);
        redeem.setRedeemTime(DateUtil.now());
        //生成交易编号
        redeem.setRedeemSerial(UUID.randomUUID().toString());
        if (!save(redeem)) throw new MwcArgsException("赎回失败", StatusCode.Error);

        return BeanUtil.copyProperties(redeem,RedeemOrderDto.class);
    }

    @Override
    public void complete() throws IOException {
        HashMap<Integer, Double> map = new HashMap<>();
        Double redeemPrice=0.0;
        //获取所有待完成的记录
        List<RedeemRecord> records = list(new QueryWrapper<RedeemRecord>().eq("redeem_record_status", 0));
        if(null==records||records.size()==0) throw new MwcArgsException("赎回记录不存在",StatusCode.Error);
        for (RedeemRecord record : records) {
            if (map.containsKey(record.getGoldId())) {//获取黄金实时价格
                redeemPrice = map.get(record.getGoldId());
            } else {
                redeemPrice = GoldUtil.getCurrentPrice(String.valueOf(record.getGoldId())).getLastPrice();
                map.put(record.getGoldId(),redeemPrice);
            }
            record.setRedeemRecordStatus(1);//完成订单
            record.setCompleteTime(DateUtil.now());
            //计算赎回费率,
            Double redeemRate = record.getRedeemRate();
            Double redeemShares = record.getRedeemShares();
            Double redeemCharge=0.0;
            QueryWrapper<FinancialShares> qw = new QueryWrapper<FinancialShares>().eq("financial_id", record.getFinancialId()).orderByAsc("financial_time");
            List<FinancialShares> shares = fss.list(qw);
            for (FinancialShares share : shares) {
                Double rate = rate(share.getFinancialTime(), redeemRate);
                if(share.getFinancialShares()>redeemShares){
                    redeemCharge+=redeemShares*redeemPrice*(1-rate);
                    share.setFinancialShares(share.getFinancialShares()-redeemShares);
                    fss.save(share);
                    break;
                } else {
                    //计算费额
                    redeemCharge+=share.getFinancialShares()*redeemPrice*(1-rate);
                    redeemShares=redeemShares-share.getFinancialShares();
                    //删除记录
                    fss.removeById(share.getFinancialSharesId());
                }
            }
            record.setRedeemCharge(redeemCharge);//实际赎回费额
            record.setRedeemPrice(redeemPrice);
            //持仓份额更新
            ufs.updateShares(record.getFinancialId(), (-1)*record.getRedeemShares());
        }
        if (!saveOrUpdateBatch(records)) throw new MwcArgsException("赎回失败", StatusCode.Error);
    }
    @Override
    public PageResult<RedeemOrderDto> queryRecord(OrderPageVo op) {
        QueryWrapper<RedeemRecord> qw = new QueryWrapper<>();
//        if (null == op.getUserId()) throw new MwcArgsException("用户id不能为空", StatusCode.Error);
        if (null!= op.getUserId())  qw.eq("user_id", op.getUserId());
        if (null!=op.getFinancialId()) qw.eq("financial_id",op.getFinancialId());
        if (null != op.getStartTime()) qw.ge("redeem_time", op.getStartTime());
        if (null != op.getEndTime()) qw.le("redeem_time", op.getEndTime());
        String keyword = op.getKeyword();
        if (!StrUtil.hasEmpty(keyword)) {
            qw.and(qwt -> {
                qwt.like("variety", keyword).or()
                        .like("redeem_serial", keyword);
            });
        }
        Page<RedeemRecord> page = page(new Page<>(op.getCurrent(), op.getSize()), qw);
        PageResult pageResult = BeanUtil.copyProperties(page, PageResult.class);
        pageResult.setData(BeanUtil.copyToList(page.getRecords(), RedeemOrderDto.class));
        pageResult.setTotalCount(page.getTotal());
        return pageResult;
    }
    public Double rate(String time,Double redeemRate){
        long gap = DateUtil.between(DateUtil.parse(time), DateUtil.date(), DateUnit.DAY);
        if (gap<7) {
            return redeemRate*1;
        }else if (gap<30){
            return redeemRate*0.5;
        }else {
            return 0D;
        }
    }
}
